package codename.primavera.web;

import java.io.IOException;
import java.io.Serializable;

import javax.faces.context.FacesContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import codename.primavera.model.User;
import codename.primavera.service.UserService;
import codename.primavera.web.security.util.SpringSecurityUtils;

/**
 * The Class LoginBean.
 */
@Component("authBean")
@Scope("request")
public class AuthenticationBean implements Serializable {

    /**
     * the serialVersionUID.
     */
    private static final long serialVersionUID = -3271438147761381664L;

    /** The Constant LOG. */
    private static final Logger LOG = LoggerFactory.getLogger(AuthenticationBean.class);

    /** The user service. */
    @Autowired
    private transient UserService userService;

    /** The user. */
    private User user = new User();

    /**
     * The admin password fill be filled in by the
     * {@link AuthenticationBean#fetchAdminPassword()} method. This will be
     * used to demonstrate method security implementation.
     */
    private String adminPassword;

    /**
     * Gets the current user.
     * @return the current user
     */
    public UserDetails getCurrentUser() {
        return SpringSecurityUtils.getUser();
    }

    /**
     * User in role.
     * @param roles the roles
     * @return true, if successful
     */
    public boolean userInRole(final String... roles) {
        return SpringSecurityUtils.userHasAtLeastOneRole(roles);
    }

    /**
     * User in role. Support for EL.
     * @param role the role
     * @return true, if successful
     */
    public boolean userInRole(final String role) {
        return userInRole(new String[] {
            role});
    }

    /**
     * Redirects the user to the Spring Security filter which handles the
     * login.
     */
    public void login() {
        LOG.info("Logging in.");
        try {
            FacesContext.getCurrentInstance().getExternalContext().dispatch("/j_spring_security_check");
            FacesContext.getCurrentInstance().responseComplete();
        } catch (IOException ioE) {
            throw new RuntimeException("Error dispatching.", ioE);
        }
    }

    /**
     * Redirects the user to the Spring Security filter which handles the
     * logout.
     */
    public void logout() {
        LOG.info("Logging out.");

        try {
            FacesContext.getCurrentInstance().getExternalContext().dispatch("/j_spring_security_logout");
            FacesContext.getCurrentInstance().responseComplete();
        } catch (IOException ioE) {
            throw new RuntimeException("Error dispatching.", ioE);
        }
    }

    /**
     * Sets the {@link AuthenticationBean#adminPassword} to the super
     * secret confidential password. Security on this service is active.
     */
    public void fetchAdminPassword() {
        adminPassword = userService.getSuperSecretConfidentialPassword();
    }

    /**
     * Gets the admin password.
     * @return the admin password
     */
    public String getAdminPassword() {
        return adminPassword;
    }

    /**
     * Gets the user.
     * @return the user
     */
    public User getUser() {
        return user;
    }

    /**
     * Sets the user.
     * @param user the new user
     */
    public void setUser(final User user) {
        this.user = user;
    }

}
